﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using ElementumForever.Utility;
using ElementumForever.Interfaces;
using ElementumForever.Factory;

namespace ElementumForever
{
    class CoordinateHelper
    {

        static public Vector2 FromSceneToPhysicalWorld(Vector2 posInScene)
        {
            float height = GraphicConstant.WINDOW_HEIGHT;
            Vector2 des = new Vector2(posInScene.X / PhysicalFactory.PixelToMeter, (height - posInScene.Y) / PhysicalFactory.PixelToMeter);
            return des;
        }

        static public Vector2 FromPhysicalWorldToScene(Vector2 posInWorld)
        {
            float height = GraphicConstant.WINDOW_HEIGHT;
            Vector2 des = new Vector2(posInWorld.X * PhysicalFactory.PixelToMeter, height - (posInWorld.Y * PhysicalFactory.PixelToMeter));
            return des;
        }

        /// <summary>
        /// Get a matrix to transform local coordinate to parent coordinate.</summary>
        /// <param name="world">
        /// entity contains information of position,rotation and scale.</param>
        /// <returns>A matrix that can transform entity local coordinate to screen coordinate.</returns>
        public static Matrix ChildToParentTransformMatrix(IEntity world)
        {
            float radians = UnitHelper.ToRadians(world.Rotation);

            Matrix translateToOrigin = Matrix.CreateTranslation(-world.OriginX, -world.OriginY, 0);
            Matrix rotationMatrix = Matrix.CreateRotationZ(radians);
            Matrix scaleMatrix = Matrix.CreateScale(new Vector3(world.ScaleX, world.ScaleY, 0));
            Matrix translateBackToPosition = Matrix.CreateTranslation(world.X, world.Y, 0);

            Matrix compositeMatrix = translateToOrigin * scaleMatrix * rotationMatrix * translateBackToPosition;//先縮放再旋轉
            return compositeMatrix;
        }

        /// <summary>
        /// Get a matrix to transform parent coordinate to child coordinate.</summary>
        /// <param name="world">
        /// entity contains information of position,rotation and scale.</param>
        /// <returns>A matrix that can transform parent entity coordinate to child coordinate.</returns>
        public static Matrix ParentToChildTransformMatrix(IEntity entity) {
            float radians = UnitHelper.ToRadians(entity.Rotation);
            Matrix backToOriginTransform = Matrix.CreateTranslation(-entity.X, -entity.Y, 0);
            Matrix rotationTransform = Matrix.CreateRotationZ(-radians);
            Matrix scaleTransform = Matrix.CreateScale(new Vector3(1f / entity.ScaleX, 1f / entity.ScaleY, 0));
            Matrix centerTransform = Matrix.CreateTranslation(entity.X, entity.Y, 0);

            Matrix finalTransform;
            finalTransform = backToOriginTransform * rotationTransform * scaleTransform * centerTransform;//先旋轉再縮放
            return finalTransform;
        }


        /// <summary>
        /// Get a matrix to transform screen coordinate to world coordinate</summary>
        /// <param name="world">entity in world coordinate</param>
        /// <returns>A matrix that can transform screen coordinate to entity local coordinate.</returns>
        public static Matrix ScreenToWorldTransformMatrix(IEntity world)
        {
            float radians = UnitHelper.ToRadians(world.Rotation);
            Matrix backToOriginTransform = Matrix.CreateTranslation(-world.X, -world.Y, 0);
            Matrix rotationTransform = Matrix.CreateRotationZ(-radians);
            Matrix scaleTransform = Matrix.CreateScale(new Vector3(1f / world.ScaleX, 1f / world.ScaleY, 0));
            Matrix centerTransform = Matrix.CreateTranslation(world.Width / 2, world.Height / 2, 0);

            Matrix finalTransform;
            finalTransform = backToOriginTransform * scaleTransform * rotationTransform * centerTransform;
            return finalTransform;
        }

        public static Vector2 FromScreenToScene(Vector2 posInScreen, IEntity scene)
        {
            return Vector2.Transform(posInScreen, scene.Unprojection);
        }

    }
}
